package com.example.xss.lixinger.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.example.xss.client.LixingerClient;
import com.example.xss.commom.enums.MetricNameEnum;
import com.example.xss.commom.util.AnalysisSourceBuildUtil;
import com.example.xss.lixinger.model.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据处理的service
 */
@AllArgsConstructor
@Slf4j
public class LixingerFormService {

    /**
     * 获取近几年的指标分析元数据
     *
     * @param numYear   年份
     * @param stockName 公司名字
     * @return map<year, 数据>
     */
    public static List<IndexAnalysisSource> getSourceOfYear(Integer numYear, String stockName) {
        Stock stock = LixingerClient.searchOne(stockName);
        if (ObjectUtil.isNull(stock)) {
            log.error("getSourceOfYear stockId is null");
            return CollUtil.newArrayList();
        }
        return getSourceOfYear(numYear, stock.get_id());
    }

    /**
     * 直接获取请求数据
     *
     * @param startDate          开始时间
     * @param endDate            结束时间
     * @param stockId            公司id
     * @param metricNameEnumList 查询字段
     * @return 查询结果
     */
    public static JSONArray getListData(LocalDateTime startDate, LocalDateTime endDate, Long stockId, List<MetricNameEnum> metricNameEnumList) {
        MetricDataReq req = MetricDataReq.builder()
                .stockIds(CollUtil.newArrayList(stockId))
                .startDate(startDate.toString())
                .endDate(endDate.toString())
                .metricsNames(metricNameEnumList.stream()
                        .map(MetricNameEnum::getValue).collect(Collectors.toList()))
                .ownerTypes(CollUtil.newArrayList("consolidated"))
                .fsReportTypeFilter("all")
                .granularities(CollUtil.newArrayList("y"))
                .expressionCaculateTypes(CollUtil.newArrayList("t", "c", "c_2y", "c_y2y", "t_c2c", "c_c2c"))
                .build();
        JSONObject json = LixingerClient.getListData(req);
        if (ObjectUtil.isNull(json)) {
            log.error("getListData res is null 请检查");
            return new JSONArray();
        }
        return json.getJSONArray("fsMetricsList");
    }

    /**
     * 获取近几年的指标分析元数据
     *
     * @param numYear 年份
     * @param stockId 公司id
     * @return map<year, 数据>
     */
    public static List<IndexAnalysisSource> getSourceOfYear(Integer numYear, Long stockId) {
        // 配置查询字段
        List<MetricNameEnum> metricNameEnumList = Arrays.stream(MetricNameEnum.values()).collect(Collectors.toList());
        // 考虑到可能会当年无法查询。先多查一天
        LocalDateTime endDate = LocalDateTime.now();
        numYear++;
        LocalDateTime startTime = endDate.plusYears(-numYear);
        List<IndexAnalysisSource> resultList = CollUtil.newArrayList();
        JSONArray fsMetricsList = getListData(startTime, endDate, stockId, metricNameEnumList);
        if (CollUtil.isEmpty(fsMetricsList)) {
            log.error("getListData fsMetricsList is empty 请检查");
            return resultList;
        }
        for (int i = 0; i < fsMetricsList.size(); i++) {
            JSONObject res = fsMetricsList.getJSONObject(i);
            // 得到该报告的年份
            String dateStr = res.getStr("date");
            LocalDateTime date = LocalDateTime.parse(dateStr.substring(0, dateStr.length() - 2));
            JSONObject y = res.getJSONObject("y");
            IndexAnalysisSource build = AnalysisSourceBuildUtil.build(y);
            build.setYear(date.getYear());
            resultList.add(build);
        }
        return resultList;
    }

    /**
     * xjl最终计算结果
     *
     * @param sourceList 源数据
     * @return 最终结果
     */
    public static CashFlowRes xjl(List<IndexAnalysisSource> sourceList) {
        CashFlowRes res = new CashFlowRes();
        if (CollUtil.isEmpty(sourceList)) {
            log.info("sourceMap is empty");
            return res;
        }
        Map<Integer, IndexAnalysisSource> sourceMap = sourceList.stream().collect(Collectors.toMap(IndexAnalysisSource::getYear, r -> r));
        for (Map.Entry<Integer, IndexAnalysisSource> entry : sourceMap.entrySet()) {
            Integer year = entry.getKey();
            // 本年
            IndexAnalysisSource yearSource = entry.getValue();
            CashFlowRes.Details build = CashFlowRes.Details.builder()
                    .year(year)
                    .yysy(yearSource.getYysy())
                    .zbkz(yearSource.getZbkz())
                    .zyxjll(yearSource.getZyxjll())
                    .gsmgsjly(yearSource.getGsmgsjly())
                    .jyyzq(yearSource.getJyyzq())
                    .sxl(yearSource.getSxl() * 100)
                    .yspj(yearSource.getYspj())
                    .yszkk(yearSource.getYszkk())
                    .btl(percentage(yearSource.getYspj(),yearSource.getYysy()))
                    .ysl(percentage(yearSource.getYszkk(),yearSource.getYysy()))
                    .build();

            res.buildList(build);
        }
        Integer zbkzSum = 0;
        Integer zyxjllSum = 0;
        Integer gsmgsjlySum = 0;
        Integer jyyzqSum = 0;
        Double sxlstrSum = 0D;
        Double yslSum = 0D;
        Double btlSum = 0D;
        for (CashFlowRes.Details details : res.getList()) {
            zbkzSum += details.getZbkz();
            zyxjllSum += details.getZyxjll();
            gsmgsjlySum += details.getGsmgsjly();
            jyyzqSum += details.getJyyzq();
            sxlstrSum += details.getSxl();
            yslSum += details.getYsl();
            btlSum += details.getBtl();
        }
        int size = res.getList().size();
        res.setJbz(percentage(zyxjllSum, zbkzSum));
        res.setZzz(percentage(gsmgsjlySum, zbkzSum));
        res.setJyyzqavg(avg(jyyzqSum, size));
        res.setSxlavg(avg(sxlstrSum, size));

        res.setBtlavg(avg(btlSum, size));
        res.setYslavg(avg(yslSum, size));
        return res;

    }

    private static Double percentage(Object val1, Object val2) {
        BigDecimal divisor = new BigDecimal(val2.toString());
        if (divisor.compareTo(new BigDecimal(0))==0) {
            return 0D;
        }
        BigDecimal divide = new BigDecimal(val1.toString()).divide(divisor, 4, RoundingMode.HALF_UP);
        return divide.multiply(new BigDecimal(100)).doubleValue();
    }
    private static Double avg(Object val1, Object val2) {
        BigDecimal divisor = new BigDecimal(val2.toString());
        if (divisor.compareTo(new BigDecimal(0))==0) {
            return 0D;
        }
        BigDecimal divide = new BigDecimal(val1.toString()).divide(divisor, 4, RoundingMode.HALF_UP);
        return divide.doubleValue();
    }


    /**
     * 计算指标分析最终结果
     *
     * @param sourceList 源数据
     * @return 最终结果
     */
    public static List<IndexAnalysisRes> indexAnalysis(List<IndexAnalysisSource> sourceList) {
        List<IndexAnalysisRes> resultList = CollUtil.newArrayList();
        if (CollUtil.isEmpty(sourceList)) {
            log.info("sourceMap is empty");
            return resultList;
        }
        // 开始计算，按理来说。最后一年没法计算
        Map<Integer, IndexAnalysisSource> sourceMap = sourceList.stream().collect(Collectors.toMap(IndexAnalysisSource::getYear, r -> r));
        for (Map.Entry<Integer, IndexAnalysisSource> entry : sourceMap.entrySet()) {
            Integer year = entry.getKey();
            if (!sourceMap.containsKey(year - 1)) {
                // 如果 前一年没有。就跳过
                continue;
            }
            // 本年
            IndexAnalysisSource yearSource = entry.getValue();
            // 去年
            IndexAnalysisSource lastYear = sourceMap.get(year - 1);
            // 营业收入增长量
            int yysrzzl = yearSource.getYysy() - lastYear.getYysy();
            // 应收账款增长量
            int yszkzzl = yearSource.getYszk() - lastYear.getYszk();
            // 存货增长量
            int chzzl = yearSource.getCh() - lastYear.getCh();
            // 自由现金流为正 差值
            int zyxjlres = yearSource.getJyhdxjlje() - yearSource.getZbkz();
            int xjljedyjlyres = yearSource.getJyhdxjlje() - yearSource.getJly();
            IndexAnalysisRes build = IndexAnalysisRes.builder()
                    .yysrzzl(yysrzzl)
                    .year(year)
                    .yszkzzl(yszkzzl)
                    .yszzldyyskres(yszkzzl - yysrzzl)
                    .yszzldyysk(yszkzzl > yysrzzl)
                    .yszzldychres(yysrzzl - chzzl)
                    .yszzldych(yysrzzl > chzzl)
                    .chzzl(chzzl)
                    .zyxjlres(zyxjlres)
                    .zyxjl(zyxjlres > 0)
                    .ldbldyres(yearSource.getLdbl())
                    .ldbldy(yearSource.getLdbl() > 1)
                    .xjljedyjlyres(xjljedyjlyres)
                    .xjljedyjly(xjljedyjlyres > 0)
                    .build();

            resultList.add(build);
        }
        return resultList;
    }


}
